home *** CD-ROM | disk | FTP | other *** search
- {*********************************************************}
- {* AAByteQ *}
- {* Copyright (c) Julian M Bucknall 1998 *}
- {* All rights reserved. *}
- {*********************************************************}
- {* Queue of bytes class *}
- {*********************************************************}
-
- {Note: this unit is released as freeware. In other words, you are free
- to use this unit in your own applications, however I retain all
- copyright to the code. JMB}
-
- unit AAByteQ;
-
- interface
-
- uses
- SysUtils,
- Windows;
-
- type
- TaaByteQueue = class
- private
- bqHead : PChar;
- bqTail : PChar;
- bqQMidPoint : PChar;
- bqQueue : PChar;
- bqQueueEnd : PChar;
- protected
- function getCapacity : integer;
- function getCount : integer;
- procedure setCapacity(aValue : integer);
- public
- constructor Create;
- destructor Destroy; override;
-
- procedure Clear;
- procedure Get(var aData; aDataLen : integer);
- function IsEmpty : boolean;
- procedure Put(var aData; aDataLen : integer);
- function Peek(aDataLen : integer) : pointer;
-
- property Capacity : integer
- read getCapacity write setCapacity;
- property Count : integer
- read getCount;
- end;
-
- implementation
-
- {===Helper routines==================================================}
- procedure NotEnoughDataError(aAvail, aReq : integer);
- begin
- raise Exception.Create(
- Format('Not enough data in queue (%s bytes) to satisfy read request (%s bytes)',
- [aAvail, aReq]));
- end;
- {====================================================================}
-
- {===TaaByteQueue=====================================================}
- constructor TaaByteQueue.Create;
- begin
- inherited Create;
- Capacity := 64;
- end;
- {--------}
- destructor TaaByteQueue.Destroy;
- begin
- if Assigned(bqQueue) then
- FreeMem(bqQueue, bqQueueEnd - bqQueue);
- inherited Destroy;
- end;
- {--------}
- procedure TaaByteQueue.Clear;
- begin
- bqHead := bqQueue;
- bqTail := bqQueue;
- end;
- {--------}
- procedure TaaByteQueue.Get(var aData; aDataLen : integer);
- var
- ByteCount : integer;
- begin
- {check for enough data}
- if (aDataLen > Count) then
- NotEnoughDataError(Count, aDataLen);
- {move the data}
- Move(bqHead^, aData, aDataLen);
- inc(bqHead, aDataLen);
- {if we've emptied the queue, move the head/tail pointers back}
- ByteCount := Count;
- if (ByteCount = 0) then begin
- bqHead := bqQueue;
- bqTail := bqQueue;
- end
- {if the head of the queue has moved into the overflow zone, move the
- data back, and reset the head/tail pointers}
- else if (bqHead >= bqQMidPoint) then begin
- Move(bqHead^, bqQueue^, ByteCount);
- bqHead := bqQueue;
- bqTail := bqHead + ByteCount;
- end;
- end;
- {--------}
- function TaaByteQueue.getCapacity : integer;
- begin
- Result := (bqQueueEnd - bqQueue) div 2;
- end;
- {--------}
- function TaaByteQueue.getCount : integer;
- begin
- Result := bqTail - bqHead;
- end;
- {--------}
- function TaaByteQueue.IsEmpty : boolean;
- begin
- Result := bqHead = bqTail;
- end;
- {--------}
- procedure TaaByteQueue.Put(var aData; aDataLen : integer);
- var
- ByteCount : integer;
- begin
- {if required, grow the queue by at least doubling its size}
- ByteCount := Count;
- while (ByteCount + aDataLen > Capacity) do
- Capacity := Capacity * 2;
- {we now have enough room, so add the new data}
- Move(aData, bqTail^, aDataLen);
- inc(bqTail, aDataLen);
- end;
- {--------}
- function TaaByteQueue.Peek(aDataLen : integer) : pointer;
- begin
- {check for enough data}
- if (aDataLen > Count) then
- NotEnoughDataError(Count, aDataLen);
- {just return the head pointer}
- Result := bqHead;
- end;
- {--------}
- procedure TaaByteQueue.setCapacity(aValue : integer);
- var
- ByteCount : integer;
- NewQueue : PChar;
- begin
- {don't allow data to be lost}
- ByteCount := Count;
- if (aValue < ByteCount) then
- aValue := ByteCount;
- {round the requested capacity to nearest 64 bytes}
- aValue := (aValue + 63) and $7FFFFFC0;
- {get a new buffer}
- GetMem(NewQueue, aValue * 2);
- {if we have data to transfer from the old buffer, do so}
- if (ByteCount <> 0) then
- Move(bqHead^, NewQueue^, ByteCount);
- {destroy the old buffer}
- if (bqQueue <> nil) then
- FreeMem(bqQueue, bqQueueEnd - bqQueue);
- {set the head/tail and other pointers}
- bqQueue := NewQueue;
- bqHead := NewQueue;
- bqTail := NewQueue + ByteCount;
- bqQueueEnd := NewQueue + (aValue * 2);
- bqQMidPoint := NewQueue + aValue;
- end;
- {====================================================================}
-
- end.
-
-